/**
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, version 2.1, dated February 1999.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the latest version of the GNU Lesser General
 * Public License as published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program (LICENSE.txt); if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package org.jamwiki.servlets;

import javax.activation.MimetypesFileTypeMap;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.jamwiki.DataAccessException;
import org.jamwiki.WikiBase;
import org.jamwiki.WikiException;
import org.jamwiki.WikiMessage;
import org.jamwiki.model.Namespace;
import org.jamwiki.model.Topic;
import org.jamwiki.utils.LinkUtil;
import org.jamwiki.utils.PseudoTopicHandler;
import org.jamwiki.utils.Utilities;
import org.jamwiki.utils.WikiLink;
import org.jamwiki.utils.WikiUtil;
import org.lightframework.jamwiki.servlets.WikiContext;
import org.springframework.web.servlet.ModelAndView;

/**
 * util class to extend jamwiki's {@link WikiUtil}, {@link ServletUtil}, {@link LinkUtil},etc.
 * 
 * @author fenghm(live.fenghm@gmail.com)
 */
public final class ServletUtilEx {
	
	/**
	 * return can current user edit current topic
	 */
	public static boolean isTopicEditable(WikiPageInfo page) throws WikiException{
		return ServletUtil.isEditable(page.getVirtualWikiName(), page.getTopicName(), ServletUtil.currentUserDetails());
	}
	
	public static boolean isTopicEditable(String wiki, String topic) throws WikiException{
		return ServletUtil.isEditable(wiki, topic, ServletUtil.currentUserDetails());
	}

	public static boolean isTopicEditable(String topic) throws WikiException{
		return ServletUtil.isEditable(WikiContext.wiki().getName(), topic, ServletUtil.currentUserDetails());
	}	
	
	/**
	 * return is spring mvc view exists
	 */
	public static boolean isViewExists(ServletContext context,HttpServletRequest request,String view) throws Exception{
		return null != context.getResource("/WEB-INF/jsp/" + view);
	}
	
	public static boolean isViewError(ModelAndView mv){
		WikiPageInfo page = (WikiPageInfo)mv.getModel().get(ServletUtil.PARAMETER_PAGE_INFO);
		if(null != page){
			return null != page.getException();
		}
		return false;
	}
	
	/**
	 * build current topic edit url,if topic is not editable for current user,return null;
	 */
	public static String buildEditTopicUrl(HttpServletRequest request,WikiPageInfo page) throws WikiException{
			WikiLink link = LinkUtil.parseWikiLink(page.getVirtualWikiName(), page.getTopicName());
			String action = Namespace.FILE_ID == link.getNamespace().getId() ? "Special:Upload" : "Special:Edit";
			
			String editLink = getContextPath(request) + "/" + page.getVirtualWikiName() + "/" + action + "?topic=" + Utilities.encodeAndEscapeTopicName(page.getTopicName());
			if (!StringUtils.isBlank(request.getParameter("topicVersionId"))) {
				editLink += "&topicVersionId=" + request.getParameter("topicVersionId");
			}
			return editLink;
	}
	
	public static String buildTopicUrlNoEdit(HttpServletRequest request,WikiPageInfo page) throws WikiException,DataAccessException{
		String context = getContextPath(request);
		return LinkUtil.buildTopicUrl(context, page.getVirtualWikiName(), page.getTopicName(), false);
	}
	
	public static Topic initializeTopic(String virtualWiki, String topicName) throws WikiException {
		Topic topic = null;
		if(!PseudoTopicHandler.isPseudoTopic(topicName)){		
			try {
				topic = WikiBase.getDataHandler().lookupTopic(virtualWiki, topicName, false, null);
			} catch (DataAccessException e) {
				throw new WikiException(new WikiMessage("error.unknown", e.getMessage()), e);
			}
			if (topic != null) {
				return topic;
			}
		}
		topic = new Topic(virtualWiki, topicName);
		WikiLink wikiLink = LinkUtil.parseWikiLink(virtualWiki, topicName);
		topic.setTopicType(WikiUtil.findTopicTypeForNamespace(wikiLink.getNamespace()));
		return topic;
	}

	/**
	 * return "" or "/contextname",never return "/"
	 */
	public static String getContextPath(HttpServletRequest request){
		String path = request.getContextPath();
		if(null == path || "/".equals(path)){
			return "";
		}else if(!path.startsWith("/")){
			return "/" + path;
		}else{
			return path;
		}
	}
	
	//internal use only,indicate is posting back to the servlet extends JAMWikiServlet
	public static boolean isPostBack(HttpServletRequest request){
		String function = request.getParameter("function");
		boolean postback = null != function && !StringUtils.isBlank(function);
		if(!postback){
			//UploadServlet postback
			String contentType = ((request.getContentType() != null) ? request.getContentType().toLowerCase() : "" );
			if (contentType.indexOf("multipart") >= 0) {
				postback = true;
			}
		}
		
		if(!postback){
			//EditServlet postback
			if(WikiContext.isEditTopic() && null != request.getParameter("save")){
				postback = true;
			}
		}
		
		return postback;
	}

	/**
	 * just to call {@link ServletUtil#viewTopic(HttpServletRequest, ModelAndView, WikiPageInfo, WikiMessage, Topic, boolean, boolean)}
	 */
	public static void viewTopic(HttpServletRequest request, ModelAndView next, WikiPageInfo pageInfo, WikiMessage pageTitle, Topic topic, boolean sectionEdit, boolean allowRedirect) throws WikiException {
		ServletUtil.viewTopic(request, next, pageInfo, pageTitle, topic, sectionEdit, allowRedirect);
	}
	
	public static Topic viewTopic(String wiki,String topic) throws WikiException{
		Topic topicObject = ServletUtil.initializeTopic(wiki, topic);
		
		WikiPageInfo pageInfo = new WikiPageInfo(WikiContext.request());
		ModelAndView mv = new ModelAndView();
		WikiMessage pageTitle = null;
		ServletUtil.viewTopic(WikiContext.request(), mv, pageInfo, pageTitle, topicObject, false, false);
		
		return topicObject;
	}
	
	public static void redirect(ModelAndView next, String virtualWiki, String destination) throws WikiException {
		ServletUtil.redirect(next, virtualWiki, destination);
	}
	
	/**
	 * utility class to get content type by file name or file ext name
	 */
	public static class MimeTypes {
		
		private static MimetypesFileTypeMap map = new MimetypesFileTypeMap();
		
		/**
		 * example : getByFileName("1.jpg") 
		 */
		public static String getByFileName(String fileName){
			return map.getContentType(fileName.toLowerCase());
		}
		
		/**
		 * example : getByFileExt("gif") , ignore case
		 */
		public static String getByFileExt(String fileExtName){
			if(!fileExtName.startsWith(".")){
				fileExtName = "." + fileExtName;
			}
			fileExtName = fileExtName.toLowerCase();
			return map.getContentType(fileExtName);
		}
	}	
}
